home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Devices and Hardware / Velocity Engine / VelEng Multiprecision / vfactor source / vgiants.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  45.9 KB  |  2,803 lines  |  [TEXT/CWIE]

  1. /**************************************************************
  2.  *
  3.  *    vgiants.c
  4.  *
  5.  *    AltiVec-based giant integer package
  6.  *  Derived from original giants.c project at 
  7.  *  Next Software, Inc.
  8.  *
  9.  *  This package is part of ongoing research in the
  10.  *    Advanced Computation Group, Apple Computer.
  11.  *    
  12.  *    c. 1999 Apple Computer, Inc.
  13.  *    All Rights Reserved.
  14.  *
  15.  *
  16.  *************************************************************/
  17.  
  18. /*
  19.     Disclaimer:    IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
  20.                 ("Apple") in consideration of your agreement to the following terms, and your
  21.                 use, installation, modification or redistribution of this Apple software
  22.                 constitutes acceptance of these terms.  If you do not agree with these terms,
  23.                 please do not use, install, modify or redistribute this Apple software.
  24.  
  25.                 In consideration of your agreement to abide by the following terms, and subject
  26.                 to these terms, Apple grants you a personal, non-exclusive license, under Apple’s
  27.                 copyrights in this original Apple software (the "Apple Software"), to use,
  28.                 reproduce, modify and redistribute the Apple Software, with or without
  29.                 modifications, in source and/or binary forms; provided that if you redistribute
  30.                 the Apple Software in its entirety and without modifications, you must retain
  31.                 this notice and the following text and disclaimers in all such redistributions of
  32.                 the Apple Software.  Neither the name, trademarks, service marks or logos of
  33.                 Apple Computer, Inc. may be used to endorse or promote products derived from the
  34.                 Apple Software without specific prior written permission from Apple.  Except as
  35.                 expressly stated in this notice, no other rights or licenses, express or implied,
  36.                 are granted by Apple herein, including but not limited to any patent rights that
  37.                 may be infringed by your derivative works or by other works in which the Apple
  38.                 Software may be incorporated.
  39.  
  40.                 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
  41.                 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
  42.                 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43.                 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
  44.                 COMBINATION WITH YOUR PRODUCTS.
  45.  
  46.                 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
  47.                 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  48.                 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  49.                 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
  50.                 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
  51.                 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
  52.                 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  53. */
  54.  
  55. #include "giantsdebug.h"
  56. #if __MWERKS__
  57. #include <altivec.h>
  58. #endif
  59. #include "vgiants.h"
  60. #include "vecarith.h"
  61. #include <Memory.h>
  62. #include <Quickdraw.h>        // for random
  63. #include <stddef.h>
  64. #include <stdlib.h>
  65. #include <math.h>
  66. #include "giantsstack.h"
  67. #include <segload.h>        // for ExitToShell
  68.  
  69. //////////////////////////////////////////////
  70. // globals
  71. //////////////////////////////////////////////
  72.  
  73. static giant    cur_recip = NULL;
  74. static giant    cur_den = NULL;
  75.  
  76.  
  77.  
  78. //////////////////////////////////////////////
  79.  
  80. #if 0
  81. #define BORROW_GIANT()    newgiantbits(DEFAULT_GIANT_BITS)
  82. #define RETURN_GIANT(a)    disposegiant(a)
  83. #else
  84. #define BORROW_GIANT()    popg()
  85. #define RETURN_GIANT(a)    pushg(1)
  86. #endif
  87.  
  88. #define ADDVECS    addvecs
  89. #define SUBVECS    subvecs
  90.  
  91. #define max(a, b) (a > b ? a : b)
  92.  
  93. #if GDEBUG 
  94.  
  95. void ASSERT_GVALID(giant g)
  96. {
  97.     GAssert((g->giantSign == -1) || (g->giantSign == 1));
  98.     
  99.     if (((long)g->vectors & 0x0f) != 0) {
  100.         DebugStr("\pvectors not 16-byte aligned.");
  101.     }
  102.     
  103.     if (g->giantDigits > g->giantCapacity) {
  104.         DebugStr("\pgiant digits overflow!");        
  105.     }
  106.     
  107.     if (g->giantDigits != 0) {
  108.         vector unsigned long    veczero = (vector unsigned long)(0);
  109.         
  110.         if (vec_all_eq(g->vectors[g->giantDigits-1], veczero)) {
  111.             DebugStr("\pMSV is zero");
  112.         }
  113.     }
  114. }
  115. #endif
  116.  
  117. static void FATAL_ERROR(long err)
  118. {
  119. #pragma unused(err)
  120.     DebugStr("\pfatal error in vgiants");
  121.     //ExitToShell();
  122. }
  123.  
  124.  
  125.  
  126.  
  127.  
  128. gmatrix
  129. newgmatrix(
  130.     void
  131. )
  132. /* Allocates space for a gmatrix struct, but does not
  133.  * allocate space for the giants. */
  134. {
  135.     return((gmatrix) malloc (4*sizeof(giant)));
  136. }
  137.  
  138.  
  139. GiantStructPtr    newgiantbits(unsigned long capacityBits)
  140. {
  141.     unsigned long    giantCapacity;
  142.     unsigned long    allocSize;
  143.     GiantStructPtr    pg;
  144.     
  145.     if (!capacityBits) capacityBits = 1;
  146.     
  147.     giantCapacity = (capacityBits + BITS_PER_VECTOR-1) / BITS_PER_VECTOR;
  148.     allocSize = giantCapacity * BYTES_PER_VECTOR;
  149.     pg = (GiantStructPtr)NewPtr(sizeof(GiantStruct));
  150.  
  151.     GAssert(pg != nil);    
  152.     
  153.     pg->giantSign = 1;
  154.     pg->giantDigits = 0;
  155.     pg->giantCapacity = giantCapacity;    
  156.     
  157.     pg->vectors = (vector unsigned long *)NewPtr(allocSize);
  158.  
  159.     GAssert(pg->vectors != nil);
  160.     
  161.     return pg;
  162. }
  163.  
  164. GiantStructPtr    newgiant(unsigned long capacityShorts)
  165. {
  166.     return newgiantbits(capacityShorts << 4);
  167. }
  168.  
  169.  
  170. void disposegiant(GiantStructPtr g)
  171. {
  172.     ASSERT_GVALID(g);
  173.     
  174.     DisposePtr((Ptr)g->vectors);    
  175.     DisposePtr((Ptr)g);
  176. }
  177.  
  178. static void reallocgdigits(giant g, unsigned long vectorcount, Boolean save)
  179. {
  180.     long                i;
  181.             
  182.     vector unsigned long *pNewVectors = (vector unsigned long *)NewPtr( vectorcount * BYTES_PER_VECTOR );
  183.  
  184.     GAssert(vectorcount >= g->giantDigits);
  185.  
  186.     GAssert(pNewVectors != nil);
  187.     
  188.     if (pNewVectors != nil) {
  189.         if (save) {
  190.             for (i=0; i<g->giantDigits; i++) {
  191.                 pNewVectors[i] = g->vectors[i];
  192.             }
  193.         }
  194.                 
  195.         DisposePtr((Ptr)g->vectors);
  196.         g->vectors = pNewVectors;
  197.         g->giantCapacity = vectorcount;
  198.     }
  199. }
  200.  
  201.  
  202.  
  203. static void reallocg(giant g, unsigned long newbits, Boolean save)
  204. {
  205.     unsigned long    vectorcount =  (newbits + 127) / 128;
  206.     
  207.     reallocgdigits(g, vectorcount, save);
  208. }
  209.  
  210. static void EnsureDigits(giant g, unsigned long newdigits, Boolean save)
  211. {
  212.     if (g->giantCapacity < newdigits) {
  213.         reallocgdigits(g, newdigits, save);
  214.     }
  215. }
  216.  
  217. static void EnsureBits(giant g, unsigned long newbits, Boolean save)
  218. {
  219.     if (g->giantCapacity * BITS_PER_VECTOR < newbits) {
  220.         reallocg(g, newbits, save);
  221.     }
  222. }
  223.  
  224. static void EnsureBytes(giant g, unsigned long newbytes, Boolean save)
  225. {
  226.     EnsureBits(g, newbytes << 3, save);
  227. }
  228.  
  229. static void AddMSDLong(giant g, unsigned long digit)
  230. {
  231.     unsigned long *topvector;
  232.  
  233.     if (g->giantCapacity == g->giantDigits) {
  234.         reallocgdigits(g, g->giantDigits+1, true);
  235.     }    
  236.     
  237.     topvector = (unsigned long*)&g->vectors[g->giantDigits];
  238.     
  239.     *topvector++ = 0;
  240.     *topvector++ = 0;
  241.     *topvector++ = 0;
  242.     *topvector = digit;
  243.     
  244.     g->giantDigits++;
  245. }
  246.  
  247. #if 1
  248. static void justg(giant g)
  249. {
  250.     if (g->giantDigits) {
  251.         unsigned long        counter = g->giantDigits;
  252.         unsigned long        *pLongs = (unsigned long*)&g->vectors[g->giantDigits];    // point to one past last
  253.  
  254.         while (counter--) {
  255.             if (*--pLongs) break;
  256.             if (*--pLongs) break;
  257.             if (*--pLongs) break;
  258.             if (*--pLongs) break;
  259.             
  260.             g->giantDigits--;
  261.         }
  262.     
  263.     }
  264.  
  265. }
  266. #else
  267. static void justg(giant g)
  268. {
  269.     if (g->giantDigits) {
  270.         vector unsigned long vecZero = (vector unsigned long)(0);
  271.         
  272.         while (vec_all_eq(vecZero, g->vectors[g->giantDigits-1]) && g->giantDigits) {
  273.             // do nothing
  274.             g->giantDigits--;
  275.         }
  276.     }
  277. }
  278. #endif
  279.  
  280. static unsigned long gtoul(giant g)
  281. {
  282.     GAssert(bitlen(g) <= 32);
  283.     
  284.     if (!g->giantSign) return 0;
  285.     
  286.     return ((unsigned long *)g->vectors)[LONGS_PER_VECTOR-1];
  287. }
  288.  
  289.  
  290.  
  291.  
  292.  
  293. int                cur_run = 0;
  294. double *        sinCos=NULL;
  295.  
  296. void
  297. init_sinCos(
  298.     int         n
  299. )
  300. {
  301.     int         j;
  302.     double     e = TWOPI/n;
  303.  
  304.     if (n<=cur_run)
  305.         return;
  306.     cur_run = n;
  307.     if (sinCos)
  308.         free(sinCos);
  309.     sinCos = (double *)malloc(sizeof(double)*(1+(n>>2)));
  310.     for (j=0;j<=(n>>2);j++)
  311.     {
  312.         sinCos[j] = sin(e*j);
  313.     }
  314. }
  315.  
  316.  
  317. double
  318. s_sin(
  319.     int     n
  320. )
  321. {
  322.     int     seg = n/(cur_run>>2);
  323.  
  324.     switch (seg)
  325.     {
  326.         case 0: return(sinCos[n]);
  327.         case 1: return(sinCos[(cur_run>>1)-n]);
  328.         case 2: return(-sinCos[n-(cur_run>>1)]);
  329.         case 3: return(-sinCos[cur_run-n]);
  330.     }
  331.     return 0;
  332. }
  333.  
  334.  
  335. double
  336. s_cos(
  337.     int     n
  338. )
  339. {
  340.     int     quart = (cur_run>>2);
  341.  
  342.     if (n < quart)
  343.         return(s_sin(n+quart));
  344.     return(-s_sin(n-quart));
  345. }
  346.  
  347.  
  348.  
  349.  
  350. unsigned char GetNthByte(giant g, unsigned long pos)
  351. {
  352.     unsigned long    byteindex;
  353.     
  354.     //GAssert(pos < g->giantDigits * BYTES_PER_VECTOR);
  355.     
  356.     if (pos >= g->giantDigits * BYTES_PER_VECTOR) {
  357.         return 0;
  358.     }
  359.     
  360.     byteindex = pos & ~0xf;
  361.     
  362.     byteindex += BYTES_PER_VECTOR - (pos & 0xf)-1;
  363.     
  364.     return ((unsigned char*)g->vectors)[byteindex];
  365.  
  366. }
  367.  
  368. static unsigned short * GetNthShortPtr(giant g, unsigned long pos)
  369. {
  370.     unsigned long    shortindex;
  371.         
  372.     if (pos >= g->giantDigits * SHORTS_PER_VECTOR) {
  373.         return 0;
  374.     }
  375.     
  376.     shortindex = pos & ~0x7;
  377.     
  378.     shortindex += SHORTS_PER_VECTOR - (pos & 0x7)-1;
  379.     
  380.     return &((unsigned short*)g->vectors)[shortindex];
  381.  
  382. }
  383.  
  384.  
  385. static unsigned long * GetNthLongPtr(giant g, unsigned long pos)
  386. {
  387.     unsigned long    longindex;
  388.         
  389.     if (pos >= g->giantDigits * LONGS_PER_VECTOR) {
  390.         return 0;
  391.     }
  392.     
  393.     longindex = pos & ~0x3;
  394.     
  395.     longindex += LONGS_PER_VECTOR - (pos & 0x3)-1;
  396.     
  397.     return &((unsigned long*)g->vectors)[longindex];
  398.  
  399. }
  400.  
  401. static unsigned long NumLongs(giant g)
  402. {
  403.     unsigned long result = 0;
  404.     unsigned long *longPtr;
  405.     unsigned long i;
  406.     
  407.     if (g->giantDigits) {
  408.         result = g->giantDigits * LONGS_PER_VECTOR;
  409.         
  410.         longPtr = (unsigned long*)&g->vectors[g->giantDigits-1];
  411.         
  412.         for (i=0; i<LONGS_PER_VECTOR; i++) {
  413.             if (*longPtr++ != 0)  break;
  414.             result--;    
  415.         }
  416.     }
  417.     
  418.     return result;
  419. }
  420.  
  421.  
  422. static unsigned long NumBytes(giant g)
  423. {
  424.     unsigned long result = 0;
  425.     unsigned char *bytePtr;
  426.     unsigned long i;
  427.     
  428.     if (g->giantDigits) {
  429.         result = g->giantDigits * BYTES_PER_VECTOR;
  430.         
  431.         bytePtr = (unsigned char*)&g->vectors[g->giantDigits-1];
  432.         
  433.         for (i=0; i<BYTES_PER_VECTOR; i++) {
  434.             if (*bytePtr++ != 0)  break;
  435.             result--;    
  436.         }
  437.     }
  438.     
  439.     return result;
  440. }
  441.  
  442. static unsigned long BytesToDigits(unsigned long bytes)
  443. {
  444.     return (bytes+(BYTES_PER_VECTOR-1))/BYTES_PER_VECTOR;
  445. }
  446.  
  447.  
  448.  
  449.  
  450. static Boolean gshiftleftsubvector(unsigned long bits, giant g)
  451. {
  452.     vector unsigned char    temp;    
  453.     vector unsigned char    shiftFactor, negShiftFactor;
  454.     vector unsigned char    vecZero;
  455.     vector unsigned long    t1, t2;
  456.     long                        i;
  457.     Boolean                    shiftedOut = false;
  458.  
  459.     ASSERT_GVALID(g);
  460.             
  461.     if (bits) {
  462.         vecZero = (vector unsigned char)(0);
  463.  
  464.         *((unsigned char*)&temp) = bits;    
  465.         
  466.         shiftFactor = vec_splat(temp, 0);                // fill vector with shift amount
  467.         negShiftFactor = vec_sub(vecZero, shiftFactor);
  468.         
  469.         // figure out if we need to expand
  470.         t2 = vec_sro(g->vectors[g->giantDigits-1], negShiftFactor);
  471.         t2 = vec_srl(t2, negShiftFactor);
  472.         if (!vec_all_eq((vector unsigned long)vecZero, t2)) {
  473.             shiftedOut = true;
  474.             g->vectors[g->giantDigits] = t2;
  475.         }
  476.  
  477.         for (i=g->giantDigits-1; i>0; i--) {
  478.             t1 = vec_slo(g->vectors[i], shiftFactor);
  479.             t1 = vec_sll(t1, shiftFactor);
  480.             t2 = vec_sro(g->vectors[i-1], negShiftFactor);
  481.             t2 = vec_srl(t2, negShiftFactor);
  482.             g->vectors[i] = vec_or(t1, t2);
  483.         }
  484.         
  485.         t1 = vec_slo(g->vectors[i], shiftFactor);
  486.         g->vectors[i] = vec_sll(t1, shiftFactor);
  487.     }
  488.         
  489.     return shiftedOut;
  490. }
  491.  
  492. void         gshiftleft(unsigned long bits, giant g)
  493. {
  494.     unsigned long    bitlength;
  495.     long            multiples;
  496.  
  497.     if (!bits) return;
  498.     if (!g->giantDigits) return;
  499.  
  500.     bitlength = bitlen(g);
  501.  
  502.     if (bitlength + bits > (g->giantCapacity*BITS_PER_VECTOR)) {
  503.         reallocg(g, bitlength + bits, true);
  504.     }
  505.     
  506.     multiples = bits >> 7;
  507.     
  508.     if (multiples) {
  509.         vector unsigned long    *pSrc;
  510.         vector unsigned long    *pDst;
  511.         unsigned long            digitCount = g->giantDigits;
  512.         
  513.         pSrc = &g->vectors[digitCount-1];
  514.         pDst = &g->vectors[digitCount+multiples-1];
  515.  
  516.         g->giantDigits += multiples;
  517.         
  518.         // move up digits
  519.         while (digitCount--) {
  520.             *pDst-- = *pSrc--;
  521.         }
  522.         
  523.         // fill remaining shifting with zeros
  524.         while (multiples--) {
  525.             *pDst-- = (vector unsigned long)(0);
  526.         }
  527.     }
  528.     
  529.     if (gshiftleftsubvector(bits & 0x7f, g)) {
  530.         g->giantDigits++;
  531.     }
  532.     
  533.     ASSERT_GVALID(g);
  534. }
  535.  
  536.  
  537. static void gshiftrightsubvector(unsigned long bits, giant g)
  538. {
  539.     vector unsigned char    temp;    
  540.     vector unsigned char    shiftFactor, negShiftFactor;
  541.     vector unsigned char    vecZero;
  542.     vector unsigned long    t1, t2;
  543.     long                        i;
  544.     
  545.     if (bits) {
  546.         vecZero = (vector unsigned char)(0);
  547.         
  548.         // set 0th element of shiftFactor to be bits
  549.         *((unsigned char*)&temp) = bits;
  550.             
  551.         shiftFactor = vec_splat(temp, 0);    // fill vector with shift amount
  552.         negShiftFactor = vec_sub(vecZero, shiftFactor);
  553.         
  554.         for (i=0; i<g->giantDigits-1; i++) {
  555.             t1 = vec_sro(g->vectors[i], shiftFactor);
  556.             t1 = vec_srl(t1, shiftFactor);
  557.             t2 = vec_slo(g->vectors[i+1], negShiftFactor);
  558.             t2 = vec_sll(t2, negShiftFactor);
  559.             g->vectors[i] = vec_or(t1, t2);
  560.         }
  561.         
  562.         t1 = vec_sro(g->vectors[i], shiftFactor);
  563.         g->vectors[i] = vec_srl(t1, shiftFactor);
  564.     }
  565. }
  566.  
  567. void         gshiftright(unsigned long bits, giant g)
  568. {
  569.     long        multiples;
  570.  
  571.     if (!bits) return;
  572.     if (!g->giantDigits) return;
  573.  
  574.     multiples = bits >> 7;
  575.     
  576.     if (multiples) {
  577.         if (multiples >= g->giantDigits) {
  578.             g->giantDigits = 0; 
  579.         } else {        
  580.             vector unsigned long    *pSrc;
  581.             vector unsigned long    *pDst;
  582.             unsigned long            newdigits = g->giantDigits-multiples;
  583.             
  584.             g->giantDigits = newdigits;
  585.             
  586.             pSrc = &g->vectors[multiples];
  587.             pDst = g->vectors;
  588.             
  589.             while (newdigits--) {
  590.                 *pDst++ = *pSrc++;
  591.             }
  592.         }
  593.     }
  594.  
  595.         
  596.     if (g->giantDigits) {
  597.         gshiftrightsubvector(bits& 0x7f, g);
  598.     }
  599.     
  600.     justg(g);
  601.     
  602.     ASSERT_GVALID(g);    
  603. }
  604.  
  605.  
  606.  
  607.  
  608. #if 1
  609. unsigned long            bitlen(giant g)
  610. {
  611.     unsigned long            length;
  612.     unsigned long             *longPtr;
  613.     unsigned long            i;
  614.     register unsigned long    longdigit;
  615.     ASSERT_GVALID(g);
  616.  
  617.     if (!g->giantDigits) return 0;
  618.     
  619.     length = length = BITS_PER_VECTOR * g->giantDigits;
  620.  
  621.     longPtr = (unsigned long*)&g->vectors[g->giantDigits-1];
  622.     
  623.     for (i=0; i<4; i++) {
  624.         longdigit = longPtr[i];
  625.  
  626.         if (!longdigit) {
  627.             length -= 32;    // bits per long
  628.         } else {
  629. #if __MWERKS__
  630.             register unsigned long leadingzeros=0;     // initialized to eliminate compiler warning
  631.             asm {
  632.                 cntlzw    leadingzeros, longdigit
  633.             }
  634.             length -= leadingzeros;            
  635. #else                
  636.             while (!(longdigit & 0x80000000)) {
  637.                 longdigit = longdigit << 1;
  638.                 length -= 1;
  639.             }
  640.  
  641. #endif        
  642.             break;    
  643.         }
  644.     }
  645.     
  646.     return length;
  647.  
  648. }
  649. #else
  650. unsigned long            bitlen(giant g)
  651. {
  652.     unsigned long            length;
  653.     unsigned long            count;
  654. #if __MWERKS__
  655.      vector unsigned long    vecones = (vector signed long)(-1);
  656. #else    
  657.     vector unsigned long    vecones = (vector unsigned long)(-1);
  658. #endif    
  659.     vector unsigned long    vecmask = (vector unsigned long)(0);
  660.     vector unsigned long    veczero = (vector unsigned long)(0);
  661.     vector unsigned long    digit;
  662.     unsigned long            longindex;
  663.     unsigned long            thelong;
  664.     
  665.     if (!g->giantDigits) return 0;
  666.     
  667.     count = 3;
  668.         
  669.     digit = g->vectors[g->giantDigits-1];
  670.     
  671.     longindex = 0;
  672.  
  673.     length = BITS_PER_VECTOR * g->giantDigits;
  674.  
  675.     vecmask = vec_sld(vecones, vecmask, 12);
  676.     
  677.     while (count-- && vec_all_eq(veczero, vec_and(vecmask, digit))) {
  678.         vecmask = vec_sld(vecones, vecmask, 12);
  679.         length -= 32;
  680.         longindex++;
  681.     }    
  682.         
  683.     thelong = ((unsigned long*)(&g->vectors[g->giantDigits-1]))[longindex];
  684.     
  685.     while (!(thelong & 0x80000000)) {
  686.         thelong = thelong << 1;
  687.         length -= 1;
  688.     }
  689.         
  690.     return length;    
  691. }
  692. #endif
  693.  
  694. long    bitval(giant g, long pos)
  695. {
  696. #if 1
  697.     return (GetNthByte(g, pos >> 3) & (1 << (pos & 0x07)));
  698. #else
  699.     unsigned char    mask;
  700.     unsigned long    byteindex;
  701.     
  702.     byteindex = (pos >> 7) << 4;
  703.     
  704.     byteindex += BYTES_PER_VECTOR - ((pos & 0x7f) >> 3)-1;
  705.     
  706.     mask = 1 << (pos & 0x07);
  707.     
  708.     return ((unsigned char*)g->vectors)[byteindex] & mask;
  709. #endif
  710. }
  711.  
  712.  
  713.  
  714. void gtog(giant a, giant b)
  715. {
  716.     long i;
  717.  
  718.     ASSERT_GVALID(a);
  719.     ASSERT_GVALID(b);
  720.  
  721.     if (b->giantCapacity < a->giantDigits) {
  722.         reallocgdigits(b, a->giantDigits, false);
  723.     }
  724.  
  725.     GAssert(b->giantCapacity >= a->giantDigits)
  726.     
  727.     
  728.     for (i=0; i<a->giantDigits; i++) {
  729.         b->vectors[i] = a->vectors[i];
  730.     }
  731.     
  732.     b->giantDigits = a->giantDigits;
  733.     b->giantSign = a->giantSign;
  734. }
  735.  
  736.  
  737. long CompareMagnitude(giant a, giant b)
  738. {
  739.     long                vectorindex, longindex;
  740.     unsigned long         *aPtr, *bPtr;
  741.  
  742.     ASSERT_GVALID(a);
  743.     ASSERT_GVALID(b);
  744.     
  745.     if (a->giantDigits > b->giantDigits) return 1;
  746.     if (a->giantDigits < b->giantDigits) return -1;
  747.  
  748.  
  749.     for (vectorindex=a->giantDigits-1; vectorindex >= 0; vectorindex--) {
  750.         aPtr = (unsigned long*)&a->vectors[vectorindex];
  751.         bPtr = (unsigned long*)&b->vectors[vectorindex];
  752.         
  753.         for (longindex = 0; longindex< LONGS_PER_VECTOR; longindex++) {
  754.             if (*aPtr > *bPtr) return 1;
  755.             if (*aPtr < *bPtr) return -1;
  756.             aPtr++;
  757.             bPtr++;        
  758.         }
  759.     }
  760.         
  761.     return 0;
  762. }
  763.  
  764.  
  765.  
  766. static void subg_normal(GiantStructPtr a, GiantStructPtr b, GiantStructPtr result)
  767. {
  768.     unsigned long endDigits = b->giantDigits;
  769.     
  770.     EnsureDigits(result, b->giantDigits, true);
  771.         
  772.     SUBVECS(a->vectors, a->giantDigits, b->vectors, b->giantDigits, result->vectors);
  773.  
  774.     result->giantDigits = endDigits;
  775.             
  776.     justg(result);
  777. }
  778.  
  779.  
  780. void addg(giant a, giant b)
  781. {
  782.     ASSERT_GVALID(a);
  783.     ASSERT_GVALID(b);
  784.  
  785.     if (isZero(a)) {
  786.         return;
  787.     }
  788.     
  789.     if (isZero(b)) {
  790.         gtog(a, b);
  791.         return;
  792.     }
  793.  
  794.     if (a->giantSign == b->giantSign) {
  795.         unsigned long    newdigits;
  796.         
  797.         newdigits = max(a->giantDigits, b->giantDigits)+1;
  798.         EnsureDigits(b, newdigits, true);
  799.         if (!ADDVECS(a->vectors, a->giantDigits, b->vectors, b->giantDigits, b->vectors)) {
  800.             newdigits--;
  801.         }
  802.         b->giantDigits = newdigits;
  803.  
  804.     } else {
  805.         if (b->giantSign > 0) {
  806.             // a is negative, b is positive
  807.             if (CompareMagnitude(b, a) >= 0) {
  808.                 subg_normal(a, b, b);
  809.             } else {
  810.                 // a neg, b pos, b<a
  811.                 subg_normal(b, a, b);
  812.                 negg(b);
  813.             }
  814.         } else {
  815.             // a is positive, b is negative
  816.             if (CompareMagnitude(b, a) < 0) {
  817.                 subg_normal(b, a, b);
  818.                 negg(b);
  819.             } else {
  820.                 // a neg, b pos, b>a
  821.                 subg_normal(a, b, b);
  822.             }            
  823.         }
  824.     }    
  825.     ASSERT_GVALID(a);
  826.     ASSERT_GVALID(b);
  827. }
  828.  
  829.  
  830.  
  831. // result = b-a
  832. void subg(giant a, giant b)
  833. {
  834.     ASSERT_GVALID(a);
  835.     ASSERT_GVALID(b);
  836.  
  837.     if (isZero(a)) {
  838.         return;
  839.     }
  840.     
  841.     if (isZero(b)) {
  842.         gtog(a, b);
  843.         negg(b);
  844.         return;
  845.     }
  846.  
  847.     if (a->giantSign != b->giantSign) {
  848.         unsigned long    newdigits;
  849.         
  850.         newdigits = max(a->giantDigits, b->giantDigits)+1;
  851.         EnsureDigits(b, newdigits, true);
  852.         if (!ADDVECS(a->vectors, a->giantDigits, b->vectors, b->giantDigits, b->vectors)) {
  853.             newdigits--;
  854.         }
  855.         b->giantDigits = newdigits;
  856.     } else {
  857.         if (b->giantSign > 0) {
  858.             // a is negative, b is positive
  859.             if (CompareMagnitude(b, a) >= 0) {
  860.                 subg_normal(a, b, b);
  861.             } else {
  862.                 // a neg, b pos, b<a
  863.                 subg_normal(b, a, b);
  864.                 negg(b);
  865.             }
  866.         } else {
  867.             // a is positive, b is negative
  868.             if (CompareMagnitude(b, a) < 0) {
  869.                 subg_normal(b, a, b);
  870.                 negg(b);
  871.             } else {
  872.                 // a neg, b pos, b>a
  873.                 subg_normal(a, b, b);
  874.             }            
  875.         }
  876.     }
  877.     
  878.     ASSERT_GVALID(a);
  879.     ASSERT_GVALID(b);
  880. }
  881.  
  882.  
  883.  
  884.  
  885.  
  886. void grammarmulg(giant a, giant b)
  887. {
  888.     unsigned long    resultdigits = a->giantDigits + b->giantDigits;
  889.     
  890.     if (isZero(b)) return;
  891.  
  892.     if (isZero(a)) {
  893.         gtog(a, b);
  894.         return;
  895.     }
  896.  
  897.     if (a->giantDigits == 1) {
  898.         if (NumLongs(a) == 1) {
  899.             
  900.             smulg(gtoul(a), b);
  901.             b->giantSign *= a->giantSign;
  902.         
  903.         } else {
  904.             EnsureDigits(b, b->giantDigits+1, true);
  905.             
  906.             VecMult1(    a->vectors,
  907.                         b->giantDigits,
  908.                         b->vectors,
  909.                         b->vectors);
  910.                         
  911.             b->giantDigits++;
  912.             
  913.             b->giantSign *= a->giantSign;
  914.             
  915.             justg(b);
  916.         }
  917.     } else  if (b->giantDigits == 1) {
  918.         if (NumLongs(b) == 1) {
  919.             unsigned long     blong = gtoul(b);
  920.             long             bsign = b->giantSign;
  921.             
  922.             gtog(a, b);
  923.             smulg(blong, b);
  924.             b->giantSign *= bsign;
  925.  
  926.         } else {
  927.             EnsureDigits(b, a->giantDigits+1, true);
  928.             
  929.             VecMult1(    b->vectors,
  930.                         a->giantDigits,
  931.                         a->vectors,
  932.                         b->vectors);
  933.                         
  934.             b->giantDigits = a->giantDigits+1;
  935.             
  936.             b->giantSign *= a->giantSign;
  937.             
  938.             justg(b);
  939.         }
  940.     } else {
  941.         GiantStructPtr     temp = BORROW_GIANT();
  942.         
  943.         if (a->giantDigits == 2 && b->giantDigits == 2) {
  944.             EnsureDigits(temp, 4, false);    
  945.  
  946.             mult2by2(    &a->vectors[1],
  947.                         &a->vectors[0],
  948.                         &b->vectors[1],
  949.                         &b->vectors[0],
  950.                         temp->vectors);
  951.                     
  952.             temp->giantDigits = 4;
  953.             
  954.             temp->giantSign = a->giantSign*b->giantSign;
  955.  
  956.             justg(temp);
  957.             
  958.             gtog(temp, b);
  959.  
  960.             RETURN_GIANT(temp);
  961.         
  962.         } else {    
  963.             EnsureDigits(temp, resultdigits, false);    
  964.  
  965.             VecMult(a->vectors,
  966.                     a->giantDigits,
  967.                     b->vectors,
  968.                     b->giantDigits,
  969.                     temp->vectors);
  970.                     
  971.             temp->giantDigits = resultdigits;
  972.             
  973.             temp->giantSign = a->giantSign*b->giantSign;
  974.             justg(temp);
  975.             
  976.             gtog(temp, b);
  977.  
  978.             RETURN_GIANT(temp);
  979.         }
  980.     }
  981.     
  982.     ASSERT_GVALID(b);
  983.     
  984. }
  985.  
  986. void
  987. karatmulg(
  988.         giant   x,
  989.         giant   y)
  990. /* y becomes x*y. */
  991. {
  992.         int     s = x->giantDigits, t = y->giantDigits, w, bits,
  993.                 sg = gsign(x)*gsign(y);
  994.         giant   a, b, c, e, f;
  995.  
  996.         if((s <= KARAT_BREAK) || (t <= KARAT_BREAK)) {
  997.                 grammarmulg(x,y);
  998.                 return;
  999.         }
  1000.         w = (s + t + 2)/4; bits = 16*w;
  1001.         
  1002.         a = BORROW_GIANT(); b = BORROW_GIANT(); c = BORROW_GIANT(); e = BORROW_GIANT(); f = BORROW_GIANT();
  1003.         gtog(x,a); if (w <= s) {a->giantDigits = w; justg(a);}
  1004.         absg(a);
  1005.         gtog(x,b); absg(b);
  1006.         gshiftright(bits, b);
  1007.  
  1008.         gtog(y,c); if (w <= t) {c->giantDigits = w; justg(c);}
  1009.         absg(c);
  1010.         absg(y);
  1011.         gshiftright(bits,y);
  1012.         gtog(a,e); addg(b,e);
  1013.         gtog(c,f); addg(y,f);
  1014.         karatmulg(e,f);  /* f := (a + b)(c + d). */
  1015.         karatmulg(c,a); /* a := a c. */
  1016.         karatmulg(b,y); /* d := b d. */
  1017.         subg(a,f); subg(y,f);
  1018.         gshiftleft(bits, y);
  1019.         addg(f, y);
  1020.         gshiftleft(bits, y);
  1021.  
  1022.         addg(a, y);
  1023.         setsign(y, sg);
  1024.         
  1025.         RETURN_GIANT(f);
  1026.         RETURN_GIANT(e);
  1027.         RETURN_GIANT(c);
  1028.         RETURN_GIANT(b);
  1029.         RETURN_GIANT(a);
  1030.  
  1031.         return;
  1032. }
  1033.  
  1034. void mulg(giant a, giant b)
  1035. {
  1036.     if((a->giantDigits <= KARAT_BREAK) || (b->giantDigits <= KARAT_BREAK)) {
  1037.         grammarmulg(a,b);
  1038.     } else {
  1039.         karatmulg(a, b);
  1040.     }
  1041. }
  1042.  
  1043.  
  1044. #if 1
  1045. /* g += i, with i non-negative. */
  1046. void         iaddg(unsigned long i,giant g)
  1047. {
  1048.     if (isZero(g)) {
  1049.         itog(i, g);
  1050.     } else {    
  1051.         ASSERT_GVALID(g);
  1052.  
  1053.         if (AddULongToVecs(g->vectors, g->giantDigits, i)) {
  1054.             AddMSDLong(g, 1);
  1055.         }
  1056.         
  1057.         justg(g);
  1058.  
  1059.         ASSERT_GVALID(g);
  1060.     }
  1061. }
  1062. #else
  1063. /* g += i, with i non-negative. */
  1064. void         iaddg(unsigned long i,giant g)
  1065. {
  1066.     giant        temp=BORROW_GIANT();
  1067.     
  1068.     ASSERT_GVALID(g);
  1069.  
  1070.     itog(i, temp);
  1071.     addg(temp, g);
  1072.  
  1073.     ASSERT_GVALID(g);
  1074.     
  1075.     RETURN_GIANT(temp);
  1076. }
  1077. #endif
  1078.  
  1079.  
  1080.  
  1081. /* Integer <-> giant. */
  1082. void itog(long n, giant g)
  1083. {
  1084.     unsigned long    absn = abs(n);
  1085.     
  1086.     if (absn) {
  1087.         unsigned long    *pLong = (unsigned long *)g->vectors;
  1088.         
  1089.         *pLong++ = 0;
  1090.         *pLong++ = 0;
  1091.         *pLong++ = 0;
  1092.         *pLong = absn;
  1093.  
  1094.         g->giantSign = (n < 0 ? -1 : 1);
  1095.         g->giantDigits = 1;
  1096.         
  1097.     } else {
  1098.         g->giantDigits = 0;
  1099.     }
  1100.         
  1101.     ASSERT_GVALID(g);    
  1102. }
  1103.  
  1104.  
  1105. #if 1
  1106. void         squareg(giant g)
  1107. {
  1108.     GiantStructPtr    temp;
  1109.     unsigned long     digits;
  1110.  
  1111.     if (isZero(g)) return;
  1112.  
  1113.     temp = BORROW_GIANT();
  1114.         
  1115.     digits = g->giantDigits * 2;
  1116.     
  1117.     EnsureDigits(temp, digits, false);    
  1118.         
  1119.     VecSquare(g->vectors,
  1120.             g->giantDigits,
  1121.             temp->vectors);
  1122.             
  1123.     temp->giantDigits = digits;
  1124.     
  1125.     temp->giantSign = 1;
  1126.     
  1127.     justg(temp);
  1128.     
  1129.     gtog(temp, g);
  1130.  
  1131.     RETURN_GIANT(temp);
  1132.     
  1133.     ASSERT_GVALID(g);
  1134. }    
  1135.  
  1136. #else
  1137. /* g *= g. */
  1138. void         squareg(giant g)
  1139. {
  1140.     ASSERT_GVALID(g);
  1141.     mulg(g, g);
  1142.  
  1143.     ASSERT_GVALID(g);
  1144.  
  1145. }
  1146. #endif
  1147.  
  1148. void         randomg(giant g, unsigned long numvecs)
  1149. {
  1150.     long i;
  1151.     
  1152.     if (numvecs > g->giantCapacity) numvecs = g->giantCapacity;
  1153.     
  1154.     for (i=0; i<numvecs*SHORTS_PER_VECTOR; i++) {
  1155.         ((unsigned short*)g->vectors)[i] = Random();
  1156.     }
  1157.     
  1158.     g->giantSign = (Random() & 1) ? -1 : 1;
  1159.     g->giantDigits = numvecs;
  1160.     
  1161.     justg(g);
  1162.  
  1163.     ASSERT_GVALID(g);
  1164. }
  1165.  
  1166.  
  1167.  
  1168.  
  1169. void
  1170. modg_via_recip(
  1171.     giant     d, 
  1172.     giant     r,
  1173.     giant     n
  1174. )
  1175. /* This is the fastest mod of the present collection.
  1176.  * n := n % d, where r is the precalculated
  1177.  * steady-state reciprocal of d. */
  1178.  
  1179. {
  1180.     int        s = (bitlen(r)-1), sign = gsign(n);
  1181.     giant     tmp, tmp2;
  1182.  
  1183.     if (isZero(d) || (gsign(d) < 0))
  1184.     {
  1185.         FATAL_ERROR(SIGN);
  1186.     }
  1187.  
  1188.     tmp = BORROW_GIANT();
  1189.     tmp2 = BORROW_GIANT();
  1190.     
  1191.     if (isone(d)) {
  1192.         itog(0, n);
  1193.         goto done;
  1194.     }
  1195.     
  1196.     absg(n);
  1197.     while (1) 
  1198.     {
  1199.         gtog(n, tmp); gshiftright(s-1, tmp);    
  1200.         mulg(r, tmp);
  1201.         gshiftright(s+1, tmp);
  1202.         mulg(d, tmp);
  1203.         subg(tmp, n);
  1204.         if (gcompg(n,d) >= 0) 
  1205.             subg(d,n);
  1206.         if (gcompg(n,d) < 0) 
  1207.             break;
  1208.     }
  1209.     if (sign >= 0)
  1210.         goto done;
  1211.     if (isZero(n))
  1212.         goto done; 
  1213.     negg(n);
  1214.     addg(d,n);
  1215. done:
  1216.     RETURN_GIANT(tmp);
  1217.     RETURN_GIANT(tmp2);
  1218.     return;
  1219. }
  1220.  
  1221. void
  1222. make_recip(
  1223.     giant     d, 
  1224.     giant     r
  1225. )
  1226. /* r becomes the steady-state reciprocal
  1227.  * 2^(2b)/d, where b = bit-length of d-1. */
  1228. {
  1229.     int        b;
  1230.     giant     tmp, tmp2;
  1231.  
  1232.     if (isZero(d) || (gsign(d) < 0))
  1233.     {
  1234.         FATAL_ERROR(SIGN);
  1235.     }
  1236.     tmp = BORROW_GIANT();
  1237.     tmp2 = BORROW_GIANT();
  1238.     itog(1, r); 
  1239.     subg(r, d); 
  1240.     b = bitlen(d); 
  1241.     addg(r, d);
  1242.     gshiftleft(b, r); 
  1243.     gtog(r, tmp2);
  1244.     while (1) 
  1245.     {
  1246.         gtog(r, tmp);
  1247.         squareg(tmp);
  1248.         gshiftright(b, tmp);
  1249.         mulg(d, tmp);
  1250.         gshiftright(b, tmp);
  1251.         addg(r, r); 
  1252.         subg(tmp, r);
  1253.         if (gcompg(r, tmp2) <= 0) 
  1254.             break;
  1255.         gtog(r, tmp2);
  1256.     }
  1257.     itog(1, tmp);
  1258.     gshiftleft(2*b, tmp);
  1259.     gtog(r, tmp2); 
  1260.     mulg(d, tmp2);
  1261.     subg(tmp2, tmp);
  1262.     itog(1, tmp2);
  1263.     while (gsign(tmp) < 0) 
  1264.     {
  1265.         subg(tmp2, r);
  1266.         addg(d, tmp);
  1267.     }
  1268.     RETURN_GIANT(tmp);
  1269.     RETURN_GIANT(tmp2);
  1270. }
  1271.  
  1272.  
  1273. void
  1274. modg(
  1275.     giant     d,
  1276.     giant     n
  1277. )
  1278. /* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
  1279. {
  1280.     if (cur_recip == NULL) {
  1281.         cur_recip = newgiantbits(1);
  1282.         cur_den = newgiantbits(1);
  1283.         gtog(d, cur_den);
  1284.         make_recip(d, cur_recip);
  1285.     } else if (gcompg(d, cur_den)) {
  1286.         gtog(d, cur_den);
  1287.         make_recip(d, cur_recip);
  1288.     }
  1289.     modg_via_recip(d, cur_recip, n);
  1290. }
  1291.  
  1292. void
  1293. divg_via_recip(
  1294.     giant     d, 
  1295.     giant     r, 
  1296.     giant     n
  1297. )
  1298. /* n := n/d, where r is the precalculated
  1299.  * steady-state reciprocal of d. */
  1300. {
  1301.     int     s = 2*(bitlen(r)-1), sign = gsign(n);
  1302.     giant     tmp, tmp2;
  1303.  
  1304.     if (isZero(d) || (gsign(d) < 0))
  1305.     {
  1306.         FATAL_ERROR(SIGN);
  1307.     }
  1308.     
  1309.     tmp = BORROW_GIANT();
  1310.     tmp2 = BORROW_GIANT();
  1311.     
  1312.     if (isone(d)) {
  1313.         // dividing by one!
  1314.         goto done;
  1315.     }
  1316.     
  1317.     absg(n);
  1318.     itog(0, tmp2);
  1319.     while (1) 
  1320.     {
  1321.         gtog(n, tmp);    
  1322.         mulg(r, tmp);
  1323.         gshiftright(s, tmp);
  1324.         addg(tmp, tmp2);
  1325.         mulg(d, tmp);
  1326.         subg(tmp, n);
  1327.         if (gcompg(n,d) >= 0)
  1328.         {
  1329.             subg(d,n);
  1330.             iaddg(1, tmp2);
  1331.         }
  1332.         if (gcompg(n,d) < 0) 
  1333.             break;
  1334.     }
  1335.     gtog(tmp2, n);
  1336.     setsign(n, gsign(n) * sign);
  1337. done:
  1338.     RETURN_GIANT(tmp);
  1339.     RETURN_GIANT(tmp2);
  1340. }
  1341.  
  1342.  
  1343.  
  1344. void
  1345. divg(
  1346.     giant     d,
  1347.     giant     n
  1348. )
  1349. /* n becomes n/d. n is arbitrary, but the denominator d must be positive! */
  1350. {
  1351.     if (cur_recip == NULL) {
  1352.         cur_recip = newgiantbits(1);
  1353.         cur_den = newgiantbits(1);
  1354.         gtog(d, cur_den);
  1355.         make_recip(d, cur_recip);
  1356.     } else if (gcompg(d, cur_den)) {
  1357.         gtog(d, cur_den);
  1358.         make_recip(d, cur_recip);
  1359.     }
  1360.     divg_via_recip(d, cur_recip, n);
  1361. }
  1362.  
  1363. static long
  1364. radixdiv(
  1365.     long                base,
  1366.     long                divisor,
  1367.     giant            thegiant
  1368. )
  1369. /* Divides giant of arbitrary base by divisor.
  1370.  * Returns remainder. Used by idivg and gread. */
  1371. {
  1372.     long                j = (thegiant->giantDigits*SHORTS_PER_VECTOR)-1;
  1373.     unsigned int         num,rem=0;
  1374.     unsigned short        *digitpointer;
  1375.  
  1376.     if (divisor == 0)
  1377.     {
  1378.         FATAL_ERROR(DIVIDEBYZERO);
  1379.     }
  1380.  
  1381.     while (j>=0)
  1382.     {
  1383.         digitpointer = GetNthShortPtr(thegiant, j);
  1384.         num=rem*base + *digitpointer;        
  1385.         *digitpointer = (unsigned short)(num/divisor);
  1386.  
  1387.         rem = num % divisor;
  1388.         --j;
  1389.     }
  1390.  
  1391.     if (divisor < 0) negg(thegiant);
  1392.  
  1393.     justg(thegiant);
  1394.  
  1395.     return(rem);
  1396. }
  1397.  
  1398. #if 1
  1399. long
  1400. idivg(
  1401.     long    divisor,
  1402.     giant     theg
  1403. )
  1404. {
  1405.     /* theg becomes theg/divisor. Returns remainder. */
  1406.     int     n;
  1407.     int     base = 1<<(8*sizeof(short));
  1408.  
  1409.     n = radixdiv(base,divisor,theg);
  1410.     return(n);
  1411. }
  1412. #else
  1413. long
  1414. idivg(
  1415.     long        divisor,
  1416.     giant         theg
  1417. )
  1418. {
  1419.     giant    originalg = BORROW_GIANT();
  1420.     giant     divisorg = BORROW_GIANT();
  1421.     long    remainder;
  1422.         
  1423.     gtog(theg, originalg);
  1424.     
  1425.     itog(divisor, divisorg);
  1426.     
  1427.     divg(divisorg, theg);
  1428.  
  1429.     mulg(theg, divisorg);
  1430.     
  1431.     subg(divisorg, originalg);
  1432.         
  1433.     remainder = gtoi(originalg);
  1434.     
  1435.     RETURN_GIANT(divisorg);
  1436.     RETURN_GIANT(originalg);
  1437.     
  1438.     return remainder;
  1439. }
  1440. #endif
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446. static void
  1447. gswap(
  1448.     giant     *p,
  1449.     giant     *q
  1450. )
  1451. {
  1452.     giant     t;
  1453.  
  1454.     t = *p;
  1455.     *p = *q;
  1456.     *q = t;
  1457. }
  1458.  
  1459.  
  1460. static void
  1461. fix(
  1462.     giant     *p,
  1463.     giant     *q
  1464. )
  1465. /* Insure that x > y >= 0. */
  1466. {
  1467.     if( gsign(*p) < 0 )
  1468.         negg(*p);
  1469.     if( gsign(*q) < 0 )
  1470.         negg(*q);
  1471.     if( gcompg(*p,*q) < 0 )
  1472.         gswap(p,q);
  1473. }
  1474.  
  1475.  
  1476. unsigned long    numtrailzeros(giant g)
  1477. {    
  1478.     unsigned long trailingbits = 0;
  1479.  
  1480.     ASSERT_GVALID(g);
  1481.     
  1482.     if (g->giantDigits != 0) {
  1483.         vector unsigned long    veczero = (vector unsigned long)(0);
  1484.         long                    vecindex;
  1485.         long                    byteindex;
  1486.         long                    bitindex;
  1487.         unsigned char            lastbyte;
  1488.         
  1489.         for (vecindex = 0; vecindex < g->giantDigits; vecindex++) {
  1490.             if (!vec_all_eq(veczero, g->vectors[vecindex])) {
  1491.                 break;
  1492.             }    
  1493.             
  1494.             trailingbits += BITS_PER_VECTOR;
  1495.         }
  1496.     
  1497.         // now go by bytes;
  1498.         for (byteindex = 0; byteindex < BYTES_PER_VECTOR; byteindex++) {
  1499.             lastbyte = GetNthByte(g, byteindex + (vecindex * BYTES_PER_VECTOR));
  1500.             if (lastbyte != 0) {
  1501.                 break;
  1502.             } 
  1503.             
  1504.             trailingbits += 8;
  1505.         }
  1506.         
  1507.         
  1508.         for (bitindex=0; bitindex < 8; bitindex++) {
  1509.             if (lastbyte & 1) {
  1510.                 break;
  1511.             }
  1512.             
  1513.             lastbyte = lastbyte >> 1;
  1514.             trailingbits++;
  1515.         }    
  1516.     }
  1517.     
  1518.     return trailingbits;
  1519. }
  1520.  
  1521. static void
  1522. dotproduct(
  1523.     giant     a,
  1524.     giant     b,
  1525.     giant     c,
  1526.     giant     d
  1527. )
  1528. /* Replace last argument with the dot product of two 2-vectors. */
  1529. {
  1530.     giant s4 = BORROW_GIANT();
  1531.  
  1532.     gtog(c,s4);
  1533.     mulg(a, s4);
  1534.     mulg(b,d);
  1535.     addg(s4,d);
  1536.     
  1537.     RETURN_GIANT(s4);
  1538. }
  1539.  
  1540.  
  1541. static   void
  1542. mulvM(
  1543.     gmatrix     A,
  1544.     giant         x,
  1545.     giant         y
  1546. )
  1547. /* Multiply vector by Matrix; changes x,y. */
  1548. {
  1549.     giant s0 = BORROW_GIANT();
  1550.     giant s1 = BORROW_GIANT();
  1551.     
  1552.     gtog(A->ur,s0);
  1553.     gtog( A->lr,s1);
  1554.     dotproduct(x,y,A->ul,s0);
  1555.     dotproduct(x,y,A->ll,s1);
  1556.     gtog(s0,x);
  1557.     gtog(s1,y);
  1558.     
  1559.     RETURN_GIANT(s0);
  1560.     RETURN_GIANT(s1);
  1561. }
  1562.  
  1563.  
  1564. static void
  1565. bgcdg(
  1566.     giant     a,
  1567.     giant     b
  1568. )
  1569. /* Binary form of the gcd. b becomes the gcd of a,b. */
  1570. {
  1571.     int        k = isZero(b), m = isZero(a);
  1572.     giant     u, v, t;
  1573.  
  1574.     if (k || m)
  1575.     {
  1576.         if (m)
  1577.         {
  1578.             if (k)
  1579.                 itog(1,b);
  1580.             return;
  1581.         }
  1582.         if (k)
  1583.         {
  1584.             if (m)
  1585.                 itog(1,b);
  1586.             else
  1587.                 gtog(a,b);
  1588.             return;
  1589.         }
  1590.     }
  1591.  
  1592.     u = BORROW_GIANT();
  1593.     v = BORROW_GIANT();
  1594.     t = BORROW_GIANT();
  1595.  
  1596.     /* Now neither a nor b is zero. */
  1597.     gtog(a, u);
  1598.     absg(u);
  1599.     gtog(b, v);
  1600.     absg(v);
  1601.     k = numtrailzeros(u);
  1602.     m = numtrailzeros(v);
  1603.     if (k>m)
  1604.         k = m;
  1605.     gshiftright(k,u);
  1606.     gshiftright(k,v);
  1607.     if (isOdd(u)) {
  1608.         gtog(v, t);
  1609.         negg(t);
  1610.     }
  1611.     else
  1612.     {
  1613.         gtog(u,t);
  1614.     }
  1615.  
  1616.     while (!isZero(t))
  1617.     {        
  1618.         m = numtrailzeros(t);
  1619.         gshiftright(m, t);
  1620.         if (gsign(t) > 0)
  1621.         {
  1622.             gtog(t, u);
  1623.             subg(v,t);
  1624.         }
  1625.         else
  1626.         {
  1627.             gtog(t, v);
  1628.             negg(v);
  1629.             addg(u,t);
  1630.         }
  1631.     }
  1632.     gtog(u,b);
  1633.     gshiftleft(k, b);
  1634.     RETURN_GIANT(v);
  1635.     RETURN_GIANT(u);
  1636.     RETURN_GIANT(t);
  1637. }
  1638.  
  1639. static void
  1640. shgcd(
  1641.     register int    x,
  1642.     register int     y,
  1643.     gmatrix         A
  1644. )
  1645. /*
  1646.  * Do a half gcd on the integers a and b, putting the result in A
  1647.  * It is fairly easy to use the 2 by 2 matrix description of the
  1648.  * extended Euclidean algorithm to prove that the quantity q*t
  1649.  * never overflows.
  1650.  */
  1651. {
  1652.     register int     q, t, start = x;
  1653.     int             Aul = 1, Aur = 0, All = 0, Alr = 1;
  1654.  
  1655.     while    (y != 0 && y > start/y)
  1656.     {
  1657.         q = x/y;
  1658.         t = y;
  1659.         y = x%y;
  1660.         x = t;
  1661.         t = All;
  1662.         All = Aul-q*t;
  1663.         Aul = t;
  1664.         t = Alr;
  1665.         Alr = Aur-q*t;
  1666.         Aur = t;
  1667.     }
  1668.     itog(Aul,A->ul);
  1669.     itog(Aur,A->ur);
  1670.     itog(All,A->ll);
  1671.     itog(Alr,A->lr);
  1672. }
  1673.  
  1674. static void
  1675. punch(
  1676.     giant         q,
  1677.     gmatrix     A
  1678. )
  1679. /* Multiply the matrix A on the left by [0,1,1,-q]. */
  1680. {
  1681.     giant s0 = BORROW_GIANT();
  1682.     
  1683.     gtog(A->ll,s0);
  1684.     mulg(q,A->ll);
  1685.     gswap(&A->ul,&A->ll);
  1686.     subg(A->ul,A->ll);
  1687.     gtog(s0,A->ul);
  1688.     gtog(A->lr,s0);
  1689.     mulg(q,A->lr);
  1690.     gswap(&A->ur,&A->lr);
  1691.     subg(A->ur,A->lr);
  1692.     gtog(s0,A->ur);
  1693.  
  1694.     RETURN_GIANT(s0);
  1695. }
  1696.  
  1697.  
  1698. static void
  1699. onestep(
  1700.     giant         x,
  1701.     giant         y,
  1702.     gmatrix     A
  1703. )
  1704. /* Do one step of the euclidean algorithm and modify
  1705.  * the matrix A accordingly. */
  1706. {
  1707.     giant s4 = BORROW_GIANT();
  1708.  
  1709.     gtog(x,s4);
  1710.     gtog(y,x);
  1711.     gtog(s4,y);
  1712.     divg(x,s4);
  1713.     punch(s4,A);
  1714.     mulg(x,s4);
  1715.     subg(s4,y);
  1716.     
  1717.     RETURN_GIANT(s4);
  1718. }
  1719.  
  1720. static void
  1721. mulmM(
  1722.     gmatrix     A,
  1723.     gmatrix     B
  1724. )
  1725. /* Multiply matrix by Matrix; changes second matrix. */
  1726. {
  1727.     giant s0 = BORROW_GIANT();
  1728.     giant s1 = BORROW_GIANT();
  1729.     giant s2 = BORROW_GIANT();
  1730.     giant s3 = BORROW_GIANT();
  1731.  
  1732.     gtog(B->ul,s0);
  1733.     gtog(B->ur,s1);
  1734.     gtog(B->ll,s2);
  1735.     gtog(B->lr,s3);
  1736.  
  1737.     dotproduct(A->ur,A->ul,B->ll,s0);
  1738.     dotproduct(A->ur,A->ul,B->lr,s1);
  1739.     dotproduct(A->ll,A->lr,B->ul,s2);
  1740.     dotproduct(A->ll,A->lr,B->ur,s3);
  1741.  
  1742.     gtog(s0,B->ul);
  1743.     gtog(s1,B->ur);
  1744.     gtog(s2,B->ll);
  1745.     gtog(s3,B->lr);
  1746.  
  1747.     RETURN_GIANT(s0);
  1748.     RETURN_GIANT(s1);
  1749.     RETURN_GIANT(s2);
  1750.     RETURN_GIANT(s3);
  1751. }
  1752.  
  1753.  
  1754.  
  1755. static void
  1756. hgcd(
  1757.     int         n,
  1758.     giant         xx,
  1759.     giant         yy,
  1760.     gmatrix     A
  1761. )
  1762. /* hgcd(n,x,y,A) chops n bits off x and y and computes th
  1763.  * 2 by 2 matrix A such that A[x y] is the pair of terms
  1764.  * in the remainder sequence starting with x,y that is
  1765.  * half the size of x. Note that the argument A is modified
  1766.  * but that the arguments xx and yy are left unchanged.
  1767.  */
  1768. {
  1769.     giant         x, y;
  1770.  
  1771.     if (isZero(yy))
  1772.         return;
  1773.     
  1774.     x = BORROW_GIANT();
  1775.     y = BORROW_GIANT();
  1776.     gtog(xx,x);
  1777.     gtog(yy,y);
  1778.     gshiftright(n,x);
  1779.     gshiftright(n,y);
  1780.     if (bitlen(x) <= INTLIMIT )
  1781.     {
  1782.         shgcd(gtoi(x),gtoi(y),A);
  1783.     }
  1784.     else
  1785.     {
  1786.         GMatrixStruct     B;
  1787.         int             m = bitlen(x)/2;
  1788.  
  1789.         hgcd(m,x,y,A);
  1790.         mulvM(A,x,y);
  1791.         if (gsign(x) < 0)
  1792.         {
  1793.             negg(x); negg(A->ul); negg(A->ur);
  1794.         }
  1795.         if (gsign(y) < 0)
  1796.         {
  1797.             negg(y); negg(A->ll); negg(A->lr);
  1798.         }
  1799.         if (gcompg(x,y) < 0)
  1800.         {
  1801.             gswap(&x,&y);
  1802.             gswap(&A->ul,&A->ll);
  1803.             gswap(&A->ur,&A->lr);
  1804.         }
  1805.         if (!isZero(y))
  1806.         {
  1807.             onestep(x,y,A);
  1808.             m /= 2;
  1809.             B.ul = BORROW_GIANT();
  1810.             B.ur = BORROW_GIANT();
  1811.             B.ll = BORROW_GIANT();
  1812.             B.lr = BORROW_GIANT();
  1813.             itog(1,B.ul);
  1814.             itog(0,B.ur);
  1815.             itog(0,B.ll);
  1816.             itog(1,B.lr);
  1817.             hgcd(m,x,y,&B);
  1818.             mulmM(&B,A);
  1819.             
  1820.             RETURN_GIANT(B.ul);
  1821.             RETURN_GIANT(B.ur);
  1822.             RETURN_GIANT(B.ll);
  1823.             RETURN_GIANT(B.lr);
  1824.         }
  1825.     }
  1826.     RETURN_GIANT(x);
  1827.     RETURN_GIANT(y);
  1828. }
  1829.  
  1830.  
  1831.  
  1832.  
  1833. static void
  1834. ggcd(
  1835.     giant     xx,
  1836.     giant     yy
  1837. )
  1838. /* A giant gcd.  Modifies its arguments. */
  1839. {
  1840.     giant             x = BORROW_GIANT();
  1841.     giant            y = BORROW_GIANT();
  1842.     GMatrixStruct     A;
  1843.  
  1844.     gtog(xx,x); gtog(yy,y);
  1845.     for(;;)
  1846.     {
  1847.         fix(&x,&y);
  1848.         if (bitlen(y) <= GCDLIMIT )
  1849.             break;
  1850.         A.ul = BORROW_GIANT();
  1851.         A.ur = BORROW_GIANT();
  1852.         A.ll = BORROW_GIANT();
  1853.         A.lr = BORROW_GIANT();
  1854.         itog(1,A.ul);
  1855.         itog(0,A.ur);
  1856.         itog(0,A.ll);
  1857.         itog(1,A.lr);
  1858.         hgcd(0,x,y,&A);
  1859.         mulvM(&A,x,y);
  1860.         RETURN_GIANT(A.ul);
  1861.         RETURN_GIANT(A.ur);
  1862.         RETURN_GIANT(A.ll);
  1863.         RETURN_GIANT(A.lr);
  1864.         fix(&x,&y);
  1865.         if (bitlen(y) <= GCDLIMIT )
  1866.             break;
  1867.         modg(y,x);
  1868.         gswap(&x,&y);
  1869.     }
  1870.     bgcdg(x,y);
  1871.     gtog(y,yy);
  1872.     RETURN_GIANT(x);
  1873.     RETURN_GIANT(y);
  1874. }
  1875.  
  1876. void
  1877. gcdg(
  1878.     giant        x,
  1879.     giant        y
  1880. )
  1881. {
  1882.     if (bitlen(y)<= GCDLIMIT)
  1883.         bgcdg(x,y);
  1884.     else
  1885.         ggcd(x,y);
  1886. }
  1887.  
  1888.  
  1889. void
  1890. cgcdg(
  1891.     giant     a,
  1892.     giant     v
  1893. )
  1894. /* Classical Euclid GCD. v becomes gcd(a, v). */
  1895. {
  1896.     giant     u, r;
  1897.  
  1898.     absg(v);
  1899.     if (isZero(a))
  1900.         return;
  1901.     
  1902.     u = BORROW_GIANT();
  1903.     r = BORROW_GIANT();
  1904.     
  1905.     gtog(a, u);
  1906.     absg(u);
  1907.     while (!isZero(v))
  1908.     {
  1909.         gtog(u, r);
  1910.         modg(v, r);
  1911.         gtog(v, u);
  1912.         gtog(r, v);
  1913.     }
  1914.     gtog(u,v);
  1915.     RETURN_GIANT(u);
  1916.     RETURN_GIANT(r);
  1917. }
  1918.  
  1919.  
  1920.  
  1921.  
  1922. static void
  1923. columnwrite(
  1924.     FILE     *filepointer,
  1925.     short     *column,
  1926.     char     *format,
  1927.     short     arg,
  1928.     int     newlines
  1929. )
  1930. /* Used by gwriteln. */
  1931. {
  1932.     char     outstring[10];
  1933.     short     i;
  1934.  
  1935.     sprintf(outstring,format,arg);
  1936.     for (i=0; outstring[i]!=0; ++i)
  1937.     {
  1938.         if (newlines)
  1939.         {
  1940.             if (*column >= COLUMNWIDTH)
  1941.             {
  1942.                 fputs("\\\n",filepointer);
  1943.                 *column = 0;
  1944.             }
  1945.         }
  1946.         fputc(outstring[i],filepointer);
  1947.         ++*column;
  1948.     }
  1949. }
  1950.  
  1951.  
  1952. void
  1953. gwrite(
  1954.     giant            thegiant,
  1955.     FILE            *filepointer,
  1956.     int                newlines
  1957. )
  1958. /* Outputs thegiant to filepointer. Output is terminated by a newline. */
  1959. {
  1960.     short            column;
  1961.     static giant    garbagegiant = NULL;
  1962.     unsigned long    *pLongStorage;
  1963.     unsigned long    numlongs = (thegiant->giantDigits * 40);    
  1964.     unsigned long    *numpointer;
  1965.     Boolean            firstdigits=true;
  1966.     
  1967.     pLongStorage = (unsigned long *)NewPtr(numlongs*sizeof(long));
  1968.     
  1969.     if (garbagegiant == NULL)
  1970.         garbagegiant = newgiantbits(1);
  1971.  
  1972.     if (isZero(thegiant))
  1973.     {
  1974.         fputs("0",filepointer);
  1975.     }
  1976.     else
  1977.     {
  1978.         numpointer = pLongStorage;
  1979.         gtog(thegiant,garbagegiant);
  1980.         absg(garbagegiant);
  1981.  
  1982.         do
  1983.         {
  1984.             *numpointer = (unsigned short)idivg(10000,garbagegiant);
  1985.             ++numpointer;
  1986.         }     while (!isZero(garbagegiant));
  1987.  
  1988.         column = 0;
  1989.         numpointer--;
  1990.  
  1991.         if (gsign(thegiant)<0) {
  1992.             columnwrite(filepointer,&column,"-",0, newlines);
  1993.         }
  1994.         
  1995.         do {
  1996.             if (firstdigits) {
  1997.                 columnwrite(filepointer,&column,"%d",*numpointer--,newlines);        
  1998.                 firstdigits = false;
  1999.             } else {
  2000.                 columnwrite(filepointer,&column,"%04d",*numpointer--,newlines);                    
  2001.             }
  2002.         } while (numpointer >= pLongStorage);
  2003.         
  2004.     }
  2005.     
  2006.     DisposePtr((Ptr)pLongStorage);
  2007. }
  2008.  
  2009. void
  2010. gwriteln(
  2011.     giant        theg,
  2012.     FILE        *filepointer
  2013. )
  2014. {
  2015.     gwrite(theg, filepointer, 1);
  2016.     fputc('\n',filepointer);
  2017. }
  2018.  
  2019.  
  2020. void
  2021. gread(
  2022.     giant             theg,
  2023.     FILE             *filepointer
  2024. )
  2025. {
  2026.     char             currentchar;
  2027.     int             isneg,size,backslash=false,numdigits=0;
  2028.     static giant    basetenthousand = NULL;
  2029.     static char        *inbuf = NULL;
  2030.     static giant    currentmult;
  2031.     
  2032.     if (basetenthousand == NULL)
  2033.         basetenthousand = newgiantbits(1);
  2034.     if (currentmult == NULL)
  2035.         currentmult = newgiantbits(1);
  2036.     if (inbuf == NULL)
  2037.         inbuf = (char*)malloc(MAX_DIGITS);
  2038.  
  2039.     itog(1, currentmult);
  2040.     itog(0, theg);
  2041.     
  2042.     currentchar = (char)fgetc(filepointer);
  2043.     if (currentchar=='-')
  2044.     {
  2045.         isneg=true;
  2046.     }
  2047.     else
  2048.     {
  2049.         isneg=false;
  2050.         if (currentchar!='+')
  2051.             ungetc(currentchar,filepointer);
  2052.     }
  2053.  
  2054.     do
  2055.     {
  2056.         currentchar = (char)fgetc(filepointer);
  2057.         if ((currentchar>='0') && (currentchar<='9'))
  2058.         {
  2059.             inbuf[numdigits]=currentchar;
  2060.             if(++numdigits==MAX_DIGITS)
  2061.                 break;
  2062.             backslash=false;
  2063.         }
  2064.         else
  2065.         {
  2066.             if (currentchar=='\\')
  2067.                 backslash=true;
  2068.         }
  2069.     } while(((currentchar!=' ') && (currentchar!='\n') &&
  2070.                 (currentchar!='\t')) || (backslash) );
  2071.     if (numdigits)
  2072.     {
  2073.         size = 0;
  2074.         do
  2075.         {
  2076.             inbuf[numdigits] = 0;
  2077.             numdigits-=4;
  2078.             if (numdigits<0)
  2079.                 numdigits=0;
  2080.                 
  2081.             itog((unsigned short)strtol(&inbuf[numdigits],NULL,10), basetenthousand);
  2082.             mulg(currentmult, basetenthousand);
  2083.             addg(basetenthousand, theg);
  2084.             itog(10000, basetenthousand);
  2085.             mulg(basetenthousand, currentmult);
  2086.  
  2087.         } while (numdigits>0);
  2088.  
  2089.  
  2090.         if (isneg) {
  2091.             setsign(theg, -1);
  2092.         } else {
  2093.             setsign(theg, 1);
  2094.         }
  2095.     }
  2096. }
  2097.  
  2098. void         gdumphex(giant g)
  2099. {
  2100.     long            i;
  2101.     unsigned char    b;
  2102.     
  2103.     if (g->giantDigits) {        
  2104.         if (g->giantSign == -1) {
  2105.             printf("-");
  2106.         }
  2107.  
  2108.         for (i=BYTES_PER_VECTOR*(g->giantDigits)-1; i>=0; i--) {
  2109.             b = GetNthByte(g, i);
  2110.             if (b == 0) {
  2111.                 printf("00");
  2112.             } else if (b<0x10) {
  2113.                 printf("0%x", b);
  2114.             } else {
  2115.                 printf("%x", b);
  2116.             }
  2117.         }
  2118.     } else {
  2119.         printf("0");
  2120.     }
  2121. }
  2122.  
  2123.  
  2124.  
  2125. void
  2126. bdivg(
  2127.     giant        v,
  2128.     giant        u
  2129. )
  2130. /* u becomes greatest power of two not exceeding u/v. */
  2131. {
  2132.     int         diff = bitlen(u) - bitlen(v);
  2133.     giant        scratch7;
  2134.  
  2135.     if (diff<0)
  2136.     {
  2137.         itog(0,u);
  2138.         return;
  2139.     }
  2140.     scratch7 = BORROW_GIANT();
  2141.     gtog(v, scratch7);
  2142.     gshiftleft(diff,scratch7);
  2143.     if (gcompg(u,scratch7) < 0)
  2144.         diff--;
  2145.     if (diff<0)
  2146.     {
  2147.         itog(0,u);
  2148.         RETURN_GIANT(scratch7);
  2149.         return;
  2150.     }
  2151.     itog(1,u);
  2152.     gshiftleft(diff,u);
  2153.  
  2154.     RETURN_GIANT(scratch7);
  2155. }
  2156.  
  2157.  
  2158.  
  2159. static giant    u0=NULL, u1=NULL, v0=NULL, v1=NULL;
  2160.  
  2161.  
  2162. static int
  2163. binvaux(
  2164.     giant     p,
  2165.     giant     x
  2166. )
  2167. /* Binary inverse method. Returns zero if no inverse exists,
  2168.  * in which case x becomes GCD(x,p). */
  2169. {
  2170.     
  2171.     giant scratch7;
  2172.  
  2173.     if (isone(x))
  2174.         return(1);
  2175.     if (!v0)
  2176.         v0 = newgiantbits(1);
  2177.     if (!v1)
  2178.         v1 = newgiantbits(1);
  2179.     if (!u1)
  2180.         u1 = newgiantbits(1);
  2181.     if (!u0)
  2182.         u0 = newgiantbits(1);
  2183.     itog(1, v0);
  2184.     gtog(x, v1);
  2185.     itog(0,x);
  2186.     gtog(p, u1);
  2187.  
  2188.     scratch7 = BORROW_GIANT();
  2189.     while(!isZero(v1))
  2190.     {
  2191.         gtog(u1, u0);
  2192.         bdivg(v1, u0);
  2193.         gtog(x, scratch7);
  2194.         gtog(v0, x);
  2195.         mulg(u0, v0);
  2196.         subg(v0,scratch7);
  2197.         gtog(scratch7, v0);
  2198.  
  2199.         gtog(u1, scratch7);
  2200.         gtog(v1, u1);
  2201.         mulg(u0, v1);
  2202.         subg(v1,scratch7);
  2203.         gtog(scratch7, v1);
  2204.     }
  2205.     
  2206.     RETURN_GIANT(scratch7);
  2207.  
  2208.     if (!isone(u1))
  2209.     {
  2210.         gtog(u1,x);
  2211.         if(gsign(x)<0) addg(p, x);
  2212.             return(0);
  2213.     }
  2214.     if(gsign(x)<0)
  2215.         addg(p, x);
  2216.     return(1);
  2217. }
  2218.  
  2219. int
  2220. binvg(
  2221.     giant     p,
  2222.     giant     x
  2223. )
  2224. {
  2225.     modg(p, x);
  2226.     return(binvaux(p,x));
  2227. }
  2228.  
  2229. static int
  2230. invaux(
  2231.     giant     p,
  2232.     giant     x
  2233. )
  2234. /* Returns zero if no inverse exists, in which case x becomes
  2235.  * GCD(x,p). */
  2236. {
  2237.  
  2238.     giant scratch7;
  2239.     
  2240.     if (isone(x))
  2241.         return(1);
  2242.     if (!v0)
  2243.         v0 = newgiantbits(1);
  2244.     if (!v1)
  2245.         v1 = newgiantbits(1);
  2246.     if (!u1)
  2247.         u1 = newgiantbits(1);
  2248.     if (!u0)
  2249.         u0 = newgiantbits(1);
  2250.     itog(1,u1);
  2251.     gtog(p, v0);
  2252.     gtog(x, v1);
  2253.     itog(0,x);
  2254.  
  2255.     scratch7 = BORROW_GIANT();
  2256.     while (!isZero(v1))
  2257.     {
  2258.         gtog(v0, u0);
  2259.         divg(v1, u0);
  2260.         gtog(u0, scratch7);
  2261.         mulg(v1, scratch7);
  2262.         subg(v0, scratch7);
  2263.         negg(scratch7);
  2264.         gtog(v1, v0);
  2265.         gtog(scratch7, v1);
  2266.         gtog(u1, scratch7);
  2267.         mulg(u0, scratch7);
  2268.         subg(x, scratch7);
  2269.         negg(scratch7);
  2270.         gtog(u1,x);
  2271.         gtog(scratch7, u1);
  2272.     }
  2273.  
  2274.     RETURN_GIANT(scratch7);
  2275.     
  2276.     if (!isone(v0))
  2277.     {
  2278.         gtog(v0,x);
  2279.         return(0);
  2280.     }
  2281.     if(gsign(x)<0)
  2282.         addg(p, x);
  2283.     return(1);
  2284. }
  2285.  
  2286.  
  2287. int
  2288. invg(
  2289.     giant     p,
  2290.     giant     x
  2291. )
  2292. {
  2293.     modg(p, x);
  2294.     return(invaux(p,x));
  2295. }
  2296.  
  2297. void
  2298. mersennemod (
  2299.     int n,
  2300.     giant g
  2301. )
  2302. /* g := g (mod 2^n - 1) */
  2303. {
  2304.     int the_sign, s;
  2305.     giant scratch3 = BORROW_GIANT();
  2306.     giant scratch4 = BORROW_GIANT();
  2307.     
  2308.     if ((the_sign = gsign(g)) < 0) absg(g);
  2309.     while (bitlen(g) > n) {
  2310.         gtog(g,scratch3);
  2311.         gshiftright(n,scratch3);
  2312.         addg(scratch3,g);
  2313.         gshiftleft(n,scratch3);
  2314.         subg(scratch3,g);
  2315.     }
  2316.     if(!isZero(g)) {
  2317.         if ((s = gsign(g)) < 0) absg(g);
  2318.         itog(1,scratch3);
  2319.         gshiftleft(n,scratch3);
  2320.         itog(1,scratch4);
  2321.         subg(scratch4,scratch3);
  2322.         if(gcompg(g,scratch3) >= 0) subg(scratch3,g);
  2323.         if (s < 0) {
  2324.             negg(g);
  2325.             addg(scratch3,g);
  2326.         }
  2327.         if (the_sign < 0) {
  2328.             negg(g);
  2329.             addg(scratch3,g);
  2330.         }
  2331.     }
  2332.     
  2333.     RETURN_GIANT(scratch3);
  2334.     RETURN_GIANT(scratch4);
  2335. }
  2336.  
  2337.  
  2338.  
  2339. int
  2340. mersenneinvg(
  2341.     int        q,
  2342.     giant     x
  2343. )
  2344. {
  2345.     int        k;
  2346.  
  2347.     if (!u0)
  2348.         u0 = newgiantbits(1);
  2349.     if (!u1)
  2350.         u1 = newgiantbits(1);
  2351.     if (!v1)
  2352.         v1 = newgiantbits(1);
  2353.  
  2354.     itog(1, u0);
  2355.     itog(0, u1);
  2356.     itog(1, v1);
  2357.     gshiftleft(q, v1);
  2358.     subg(u0, v1);
  2359.     mersennemod(q, x);
  2360.     while (1)
  2361.     {
  2362.         k = -1;
  2363.         if (isZero(x))
  2364.         {
  2365.             gtog(v1, x);
  2366.             return(0);
  2367.         }
  2368.         while (bitval(x, ++k) == 0)
  2369.             ;
  2370.  
  2371.         gshiftright(k, x);
  2372.         if (k)
  2373.         {
  2374.             gshiftleft(q-k, u0);
  2375.             mersennemod(q, u0);
  2376.         }
  2377.         if (isone(x))
  2378.             break;
  2379.         addg(u1, u0);
  2380.         mersennemod(q, u0);
  2381.         negg(u1);
  2382.         addg(u0, u1);
  2383.         mersennemod(q, u1);
  2384.         if (!gcompg(v1,x))
  2385.             return(0);
  2386.         addg(v1, x);
  2387.         negg(v1);
  2388.         addg(x, v1);
  2389.         mersennemod(q, v1);
  2390.     }
  2391.     gtog(u0, x);
  2392.     mersennemod(q,x);
  2393.     return(1);
  2394. }
  2395.  
  2396. void
  2397. powermod(
  2398.     giant        x,
  2399.     int         n,
  2400.     giant         g
  2401. )
  2402. /* x becomes x^n (mod g). */
  2403. {
  2404.     giant scratch2 = BORROW_GIANT();
  2405.     gtog(x, scratch2);
  2406.     itog(1, x);
  2407.     while (n)
  2408.     {
  2409.         if (n & 1)
  2410.         {
  2411.             mulg(scratch2, x);
  2412.             modg(g, x);
  2413.         }
  2414.         n >>= 1;
  2415.         if (n)
  2416.         {
  2417.             squareg(scratch2);
  2418.             modg(g, scratch2);
  2419.         }
  2420.     }
  2421.     
  2422.     RETURN_GIANT(scratch2);
  2423. }
  2424.  
  2425.  
  2426. void
  2427. powermodg(
  2428.     giant        x,
  2429.     giant        n,
  2430.     giant        g
  2431. )
  2432. /* x becomes x^n (mod g). */
  2433. {
  2434.     int         len, pos;
  2435.     giant        scratch2 = BORROW_GIANT();
  2436.  
  2437.     gtog(x, scratch2);
  2438.     itog(1, x);
  2439.     len = bitlen(n);
  2440.     pos = 0;
  2441.     while (1)
  2442.     {
  2443.         if (bitval(n, pos++))
  2444.         {
  2445.             mulg(scratch2, x);
  2446.             modg(g, x);
  2447.         }
  2448.         if (pos>=len)
  2449.             break;
  2450.         squareg(scratch2);
  2451.         modg(g, scratch2);
  2452.     }
  2453.     RETURN_GIANT(scratch2);
  2454. }
  2455.  
  2456.  
  2457. void
  2458. fermatpowermod(
  2459.     giant     x,
  2460.     int        n,
  2461.     int        q
  2462. )
  2463. /* x becomes x^n (mod 2^q+1). */
  2464. {
  2465.     giant scratch2 = BORROW_GIANT();
  2466.     
  2467.     gtog(x, scratch2);
  2468.     itog(1, x);
  2469.     while (n)
  2470.     {
  2471.         if (n & 1)
  2472.         {
  2473.             mulg(scratch2, x);
  2474.             fermatmod(q, x);
  2475.         }
  2476.         n >>= 1;
  2477.         if (n)
  2478.         {
  2479.             squareg(scratch2);
  2480.             fermatmod(q, scratch2);
  2481.         }
  2482.     }
  2483.     RETURN_GIANT(scratch2);
  2484. }
  2485.  
  2486.  
  2487. void
  2488. fermatpowermodg(
  2489.     giant     x,
  2490.     giant    n,
  2491.     int        q
  2492. )
  2493. /* x becomes x^n (mod 2^q+1). */
  2494. {
  2495.     int        len, pos;
  2496.     giant    scratch2 = BORROW_GIANT();
  2497.  
  2498.     gtog(x, scratch2);
  2499.     itog(1, x);
  2500.     len = bitlen(n);
  2501.     pos = 0;
  2502.     while (1)
  2503.     {
  2504.         if (bitval(n, pos++))
  2505.         {
  2506.             mulg(scratch2, x);
  2507.             fermatmod(q, x);
  2508.         }
  2509.         if (pos>=len)
  2510.             break;
  2511.         squareg(scratch2);
  2512.         fermatmod(q, scratch2);
  2513.     }
  2514.     RETURN_GIANT(scratch2);
  2515. }
  2516.  
  2517.  
  2518. void
  2519. mersennepowermod(
  2520.     giant     x,
  2521.     int        n,
  2522.     int        q
  2523. )
  2524. /* x becomes x^n (mod 2^q-1). */
  2525. {
  2526.     giant scratch2 = BORROW_GIANT();
  2527.  
  2528.     gtog(x, scratch2);
  2529.     itog(1, x);
  2530.     while (n)
  2531.     {
  2532.         if (n & 1)
  2533.         {
  2534.             mulg(scratch2, x);
  2535.             mersennemod(q, x);
  2536.         }
  2537.         n >>= 1;
  2538.         if (n)
  2539.         {
  2540.             squareg(scratch2);
  2541.             mersennemod(q, scratch2);
  2542.         }
  2543.     }
  2544.     RETURN_GIANT(scratch2);
  2545. }
  2546.  
  2547.  
  2548. void
  2549. mersennepowermodg(
  2550.     giant     x,
  2551.     giant    n,
  2552.     int        q
  2553. )
  2554. /* x becomes x^n (mod 2^q-1). */
  2555. {
  2556.     int        len, pos;
  2557.     giant    scratch2 = BORROW_GIANT();
  2558.  
  2559.     gtog(x, scratch2);
  2560.     itog(1, x);
  2561.     len = bitlen(n);
  2562.     pos = 0;
  2563.     while (1)
  2564.     {
  2565.         if (bitval(n, pos++))
  2566.         {
  2567.             mulg(scratch2, x);
  2568.             mersennemod(q, x);
  2569.         }
  2570.         if (pos>=len)
  2571.             break;
  2572.         squareg(scratch2);
  2573.         mersennemod(q, scratch2);
  2574.     }
  2575.     RETURN_GIANT(scratch2);
  2576. }
  2577.  
  2578.  
  2579.  
  2580. void
  2581. fermatmod (
  2582.     int             n,
  2583.     giant             g
  2584. )
  2585. /* g := g (mod 2^n + 1). */
  2586. {
  2587.     int the_sign, s;
  2588.     giant scratch3 = BORROW_GIANT();
  2589.     
  2590.     if ((the_sign = gsign(g)) < 0) absg(g);
  2591.     while (bitlen(g) > n) {
  2592.         gtog(g,scratch3);
  2593.         gshiftright(n,scratch3);
  2594.         subg(scratch3,g);
  2595.         gshiftleft(n,scratch3);
  2596.         subg(scratch3,g);
  2597.     }
  2598.     if(!isZero(g)) {
  2599.         if ((s = gsign(g)) < 0) absg(g);
  2600.         itog(1,scratch3);
  2601.         gshiftleft(n,scratch3);
  2602.         iaddg(1,scratch3);
  2603.         if(gcompg(g,scratch3) >= 0) subg(scratch3,g);
  2604.         if (s < 0) {
  2605.             negg(g);
  2606.             addg(scratch3,g);
  2607.         }
  2608.         if (the_sign < 0) {
  2609.             negg(g);
  2610.         }
  2611.     }
  2612.     
  2613.     RETURN_GIANT(scratch3);
  2614. }
  2615.  
  2616.  
  2617. #if 1
  2618. void
  2619. smulg(
  2620.     unsigned long    i,
  2621.     giant             g
  2622. )
  2623. {
  2624.     if (!i) {
  2625.         g->giantDigits = 0;
  2626.         return;
  2627.     }
  2628.     
  2629.     if (!isZero(g)) {    
  2630.         unsigned long topresult = MultVecsByULong(    g->vectors,
  2631.                                                     g->giantDigits,
  2632.                                                     i);
  2633.  
  2634.         if (topresult) {
  2635.             AddMSDLong(g, topresult);
  2636.         }
  2637.     }
  2638.     
  2639.     ASSERT_GVALID(g);
  2640. }
  2641. #else
  2642. void
  2643. smulg(
  2644.     unsigned short    i,
  2645.     giant             g
  2646. )
  2647. /* g becomes g * i. */
  2648. {
  2649.     giant    temp = BORROW_GIANT();
  2650.     
  2651.     itog(i, temp);
  2652.     
  2653.     mulg(temp, g);
  2654.     
  2655.     RETURN_GIANT(temp);
  2656.  
  2657. }
  2658. #endif
  2659.  
  2660. long            icompg(unsigned long i, giant g)
  2661. {
  2662.     long    result;
  2663.  
  2664.     giant    temp = BORROW_GIANT();
  2665.     
  2666.     itog(i, temp);
  2667.     result = gcompg(temp, g);    
  2668.     
  2669.     RETURN_GIANT(temp);
  2670.     
  2671.     return result;
  2672. }
  2673.  
  2674.  
  2675. void         trunctobitlen(long len, giant g)
  2676. {
  2677.     unsigned long     neededDigits;
  2678.     unsigned long     trimbits;
  2679.     unsigned char    *pDigit;
  2680.     unsigned char     maskByte;
  2681.     long            i;
  2682.     
  2683.     if (bitlen(g) < len) return;
  2684.  
  2685.     neededDigits = (len + BITS_PER_VECTOR - 1)/BITS_PER_VECTOR;
  2686.     
  2687.     g->giantDigits = neededDigits;
  2688.     
  2689.     trimbits = len & 0x7f;
  2690.     
  2691.     trimbits = BITS_PER_VECTOR - trimbits;
  2692.     
  2693.     if (trimbits) {
  2694.         pDigit = (unsigned char*)&g->vectors[neededDigits-1];
  2695.  
  2696.         for (i=0; i<trimbits >> 3; i++) {
  2697.             pDigit[i] = 0;
  2698.         }    
  2699.         
  2700.         trimbits &= 0x07;
  2701.         maskByte = 0xff;
  2702.         
  2703.         maskByte = maskByte >> trimbits;
  2704.         
  2705.         pDigit[i] &= maskByte;
  2706.         
  2707.     }
  2708. }
  2709.  
  2710.  
  2711. #if !INLINE_GIANTS
  2712.  
  2713. /* Returns 1, 0, -1 as a>b, a=b, a<b. */
  2714. long gcompg(giant a, giant b)
  2715. {
  2716.     ASSERT_GVALID(a);
  2717.     ASSERT_GVALID(b);
  2718.  
  2719.     if (a->giantSign > b->giantSign) return 1;
  2720.     if (a->giantSign < b->giantSign) return -1;
  2721.     
  2722.     return a->giantSign * CompareMagnitude(a, b);
  2723. }
  2724.  
  2725. signed long        gtoi (giant g)
  2726. {
  2727.     GAssert(bitlen(g) <= 32);
  2728.     
  2729.     if (!g->giantSign) return 0;
  2730.     
  2731.     return g->giantSign * ((unsigned long *)g->vectors)[LONGS_PER_VECTOR-1];
  2732. }
  2733.  
  2734. /* Returns the giantSign of g: -1, 0, 1. */
  2735. long             gsign(giant g)
  2736. {
  2737.     ASSERT_GVALID(g);
  2738.     
  2739.     if (!g->giantDigits) return 0;
  2740.     
  2741.     return g->giantSign;
  2742. }
  2743.  
  2744. void         negg(giant g)
  2745. {
  2746.     g->giantSign = -g->giantSign;
  2747. }
  2748.  
  2749. void        setsign(giant g, long sign)
  2750. {
  2751.     if (sign > 0) {
  2752.         g->giantSign = 1;
  2753.     } else {
  2754.         g->giantSign = -1;
  2755.     }
  2756. }
  2757.  
  2758. void        absg(giant g)
  2759. {
  2760.     if (g->giantSign < 0) g->giantSign = 1;
  2761. }
  2762.  
  2763. long isZero(giant g)
  2764. {
  2765.     ASSERT_GVALID(g);
  2766.  
  2767.     return (g->giantDigits == 0);
  2768. }
  2769.  
  2770. Boolean    isone(giant g)
  2771. {
  2772.     Boolean                    result = false;
  2773.     unsigned long             *pLongPtr;
  2774.     unsigned long            accumulator;
  2775.     long                    counter;
  2776.     
  2777.     if (g->giantSign == 1 && g->giantDigits == 1) {
  2778.         pLongPtr = (unsigned long*)g->vectors;
  2779.         accumulator = 0;
  2780.         for (counter=0; counter < LONGS_PER_VECTOR -1 ; counter++) {
  2781.             accumulator |= pLongPtr[counter];
  2782.         }
  2783.         
  2784.         // if first three longs are zero
  2785.         if (!accumulator) {
  2786.             // and last one is one, then it's one
  2787.             result = (pLongPtr[counter] == 1);
  2788.         }
  2789.     }
  2790.     
  2791.     return result;
  2792.  
  2793. }
  2794.  
  2795. Boolean            isOdd(giant g)
  2796. {
  2797.     return (GetNthByte(g, 0) & 0x01);
  2798. }
  2799.  
  2800.  
  2801. #endif //#if INLINE_GIANTS
  2802.  
  2803.